package com.dd.da.config.auth;

import cn.hutool.core.collection.CollectionUtil;
import com.dd.da.service.UserClient;
import com.dd.dc.common.AuthConstants;
import com.dd.dc.entity.users.DPermission;
import com.dd.dc.entity.users.DUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述: UserDetail 类
 * MyUserDetailsService里面可以用来获取数据库中的密码然后打包返回用户信息给security做用户校验使用，
 * 后者校验如果与登录的密码match，如果成功，返回UserDetail对象（用户信息对象）,进入自定义登录成功后
 * 处理类MyAuthenticationSuccessHandler。如果失败，
 * 直接进入登录失败处理类MyAuthenticationFailHandler。
 *
 * @author: yanglin
 * @Date: 2021-03-05-11:22
 * @Version: 1.0
 */
@Slf4j
@Component
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserClient userClient;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("登录用户名: {}", username);
        if (Objects.isNull(username)) {
            throw new RuntimeException("账户为空！");
        }
        DUser user = DUser.builder().build();
        user.setUserAccount(username);
        user = userClient.queryUserOne(user);
        if (Objects.isNull(user)){
            throw new RuntimeException("账户不存在！");
        }
        // 查询权限
        DUser uprInfo = userClient.queryUserInfo(user.getUserId());
        List<DPermission> permissions = uprInfo.getPermissions();
          if (Objects.isNull(permissions)){
            throw new RuntimeException("权限不存在！");
        }
        user.setRoles(uprInfo.getRoles());
        List<String> rules = permissions.stream().map(p -> p.getPRule()).collect(Collectors.toList());
        String ruleStr = String.join(",", rules);
        // 存储信息到redis
        boolean role_flag = redisTemplate.delete(AuthConstants.PERMISSION_ROLES_KEY);
        if (role_flag){
            log.info("用户权限信息重新存储");
            Map<String, List<String>> permissionRoles = new TreeMap<>();
            Optional.ofNullable(permissions).orElse(new ArrayList<>()).forEach(permission -> {
                // 转换 roleId -> ROLE_{roleId}
                List<String> roles = Optional.ofNullable(uprInfo.getRoles())
                        .orElse(new ArrayList<>())
                        .stream()
                        .map(role -> AuthConstants.AUTHORITY_PREFIX + role.getRoleId())
                        .collect(Collectors.toList());

                if (CollectionUtil.isNotEmpty(roles)) {
                    String pKey = permission.getPReqType() + "_" + permission.getPUrl();
                    permissionRoles.put(pKey, roles);
                }
                redisTemplate.opsForHash().putAll(AuthConstants.PERMISSION_ROLES_KEY, permissionRoles);
            });
        }
        return new User(user.getUserAccount(), user.getUserPassword(),
                true,true,true,true,
                AuthorityUtils.commaSeparatedStringToAuthorityList(ruleStr));
    }
}
